<?php

namespace App\Services\Oauth\Oauth2;

use Illuminate\Support\Facades\Redis;
use App\Services\Oauth\Oauth2\App;
use App\Services\User\User;
use Illuminate\Http\Request;
use App\Services\Oauth\Oauth2\AccessToken;
use App\Exceptions\Response\Service\ServiceCode;
use App\Exceptions\Response\Service\ServiceException;

/**
 * oauth2的实现（资源令牌）
 * 验证申请令牌参数，及颁发令牌（access_token）
 */
class Oauthor extends App
{
    //客户端向认证服务器申请令牌的HTTP请求参数(grant_type、redirect_uri、client_id、app_secret、code)
    protected $params;

    public function __construct($appkey = '')
    {
        parent::__construct();
        if (!$appkey) {
            throw new ServiceException(ServiceCode::SERVICE_OAUTH_APP_KEY_NOT_EXIST, '', []);
        }
        $this->setAppKey($appkey);//获取app_key
        $this->getAppInfo();//包括(app_key、app_secret、name、detail、domain、status、)
    }

    /**
     * 请求令牌参数验证
     * 客户端向认证服务器申请令牌（access_token）的HTTP请求检查
     * 传入的参数有（app_key、app_secret、grant_type、redirect_uri、code）5个
     * app_key：表示客户端ID，必选项。
     * app_secret：表示客户的secret
     * grant_type：表示使用的授权模式，必选项，此处的值固定为"authorization_code"。
     * redirect_uri：表示重定向URI，必选项，且必须与A步骤中的该参数值保持一致。
     * code：表示上一步获得的授权码，必选项。
     */
    public function checkParams($app_secret, $grant_type, $redirect_uri, $code)
    {
        /* -------接受参数列表------ */
        //grant_type ='authorization_code'
        $params = array(
            "app_secret" => $app_secret,
            "grant_type" => $grant_type,
            "redirect_uri" => urldecode($redirect_uri),
            "code" => $code
        );
        foreach ($params as $key => $value) {
            $this->params($key, $value);
        }
        $this->params = $params;
    }

    /**
     * 处理参数 返回错误描述
     * @param type $name
     * @param type $value
     */
    private function params($name, $value)
    {
        switch ($name) {
            case 'grant_type':
                if ($value !== 'authorization_code') {
                    throw new ServiceException(ServiceCode::SERVICE_OAUTH_AUTHORIZATION_CODE_NO_SUPPORTED, '', []);
                }
                break;
            case 'redirect_uri':
                //授权接入和申请时登记的域名是否匹配
                if ($this->read('domain') !== $this->baseUrl($value)) {
                    throw new ServiceException(ServiceCode::SERVICE_OAUTH_REDIRECT_MISMATCH, '', []);
                }
                break;
            case 'app_secret':
                //验证app_secret参数
                if ($value !== $this->app['app_secret']) {
                    throw new ServiceException(ServiceCode::SERVICE_OAUTH_APP_SECRET_WRONG, '', []);
                }
            default:
                if (!$value) {
                    throw new ServiceException(ServiceCode::SERVICE_OAUTH_VALUE_NOT_EXIST, '', []);
                }
                break;
        }
    }

    /**
     * 验证授权码code的有效性，保证数据的有效性
     * 客户端向认证服务器申请令牌的HTTP请求参数(grant_type、redirect_uri、client_id、app_secret、code)
     */
    public function checkCode()
    {
        //获取客户端传入的授权码code
        $this->setCode($this->params['code']);
        //到数据库查询code_data相关信息，包括（userId、app_key、scope、redirect_uri、response_type、time、state）
        $codeData = $this->getCodeData();
        if (!$codeData) {
            throw new ServiceException(ServiceCode::SERVICE_OAUTH_CODE_DATA_EMPTY, '', []);
        }
        //根据传入的参数生成授权码（code）
        $serviceCode = $this->makeCode(
            $this->app_key, $this->params['redirect_uri'], $this->params['app_secret'], $codeData['time']
        );
        //验证code的有效性，将生成的code和传入的code做比较
        if ($serviceCode !== $this->params['code']) {
            throw new ServiceException(ServiceCode::SERVICE_OAUTH_CODE_IS_WRONG, '', []);
        }
    }


    /**
     * 客户端向认证服务器申请令牌（access_token）
     * 生成令牌（access_token）
     */
    public function createAuthorize()
    {
        //查询code_data的相关信息(tw_passport_code表的code_data字段)
        //（userId、app_key、scope、redirect_uri、response_type、time、state）
        $code_data = $this->getCodeData();
        if (!$code_data['userId']) {
            throw new ServiceException(ServiceCode::SERVICE_OAUTH_USER_NOT_EXIST, '', []);
        }
        //验证授权码code成功，生成资源访问令牌（access_token）,
        $data = AccessToken::makeAuthorize($code_data['scope'], $code_data['userId']);
        if ($data) {
            //生成资源访问令牌（access_token）成功后，清除code_data
            $this->deleteCodeData();
        }
        return $data;
    }


}